/*
 * Copyright (c) 2010-2013 Ruben Chakhmakhchyan. All rights reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Eclipse Public License
 * Version 1.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://opensource.org/licenses/EPL-1.0 and read it before using this file.
 */

#pragma once


#include "async_invoke.h"
#include "plugin_model.h"
#include "image_list.h"


typedef void ( *AsyncFunctionPtr )( void* );


class PluginAsyncInvoke : public AsyncInvoke
{
public:

    AsyncFunctionPtr function;
    AsyncCallback callback;
    AsyncInvokeArg* arg;
    void* handle;
    HANDLE threadHandle;

    PluginAsyncInvoke() : function( 0 ), arg( 0 ), handle( 0 ), callback( 0 ) { }

    virtual ~PluginAsyncInvoke()
    {
        delete arg;
    }

    virtual AsyncCallback getCallback() { return callback; }
    virtual AsyncInvokeArg* getArg() { return arg; }
};


#ifndef _ADDON
class UploadAsyncArg : public AsyncInvokeArg
{
public:
    //PluginModel* model;
    char* m_url; // the url to upload to
    char* m_navigatorUrl; // current browser url
    char* m_userAgent; // current user agent the plugin instance in running in
    void* m_data; // data
    size_t m_dataLength; // file data length
    char* m_mimeType; // mime type of the file
    DocumentFormat m_format; // document format
    List<char*>* m_filenames; // file name specified in a form data
    int* m_indices; // indices of images the document would consist of
    int m_indexCount; // number of elements in indices array
    ImageList* m_list;
    //int m_filenameCount;

    UploadAsyncArg( PluginModel* model, char* url, char* navigatorUrl, char* userAgent, char* mimeType, DocumentFormat format, void* data, size_t dataLength, List<char*>* filenames, int indices[], int indexCount, int id )
        : AsyncInvokeArg( model, id ),
        m_list( NULL )
    {
        m_url = url;
        m_navigatorUrl = navigatorUrl;
        m_userAgent = userAgent;
        m_mimeType = mimeType;
        m_data = data;
        m_dataLength = dataLength;
        m_format = format;
        m_filenames = filenames;
        m_indices = indices;
        m_indexCount = indexCount;
        //m_filenameCount = filenameCount;
    }

    virtual ~UploadAsyncArg()
    {
        if ( m_data ) delete m_data;
        if ( m_mimeType ) delete m_mimeType;
        if ( m_url ) delete m_url;
        if ( m_navigatorUrl ) delete m_navigatorUrl;
        if ( m_filenames )
        {
            /*for ( int i = 0; i < m_filenameCount; i++ )
            delete ( *m_filenames )[ i ];*/
            m_filenames->destroy();

            delete m_filenames;
        }
        if ( m_list ) delete m_list;
    }

    inline char* getUserAgent() { return m_userAgent; }
    inline char* getUrl() { return m_url; }
    inline char* getNavigatorUrl() { return m_navigatorUrl; }
    inline char* getMimeType() { return m_mimeType; }
    inline List<char*>* getFilenames() { return m_filenames; }
    //inline int getFilenameCount() { return m_filenameCount; }
    inline int* getIndices() { return m_indices; }
    inline int getIndexCount() { return m_indexCount; }
    inline DocumentFormat getFormat() { return m_format; }
    inline void* getData() { return m_data; }
    inline void setData( void* data, size_t length ) { m_data = data; m_dataLength = length; }
    inline ImageList* getDataList() { return m_list; }
    inline void setDataList( ImageList* list ) { m_list = list; }
    inline size_t getDataLength() { return m_dataLength; }
    //inline size_t getUploadId() { return m_uploadId; }
};
#endif


class ScanAsyncArg : public AsyncInvokeArg
{
public:
    //PluginModel* model;
    //char* m_userAgent;
    bool m_add;
    int m_numberOfImages; // number of images scanned in this session

    ScanAsyncArg( PluginModel* model, bool add )
        : AsyncInvokeArg( model ),
        m_numberOfImages( 0 )
    {
        m_add = add;
    }

    virtual ~ScanAsyncArg() { }

    inline bool getAdd() { return m_add; }
    inline int getNumberOfImages() { return m_numberOfImages; }
    inline void setNumberOfImages( int value ) { m_numberOfImages = value; }
};

class SaveAsyncArg : public AsyncInvokeArg
{
public:

    wchar_t* m_path; // the path to save to
    DocumentFormat m_format; // document format
    List<wchar_t*>* m_filenames; // list of file names
    int* m_indices; // indices of images the document would consist of
    int m_indexCount; // number of elements in indices array
    bool m_multipage;

    SaveAsyncArg( PluginModel* model, wchar_t* path, DocumentFormat format, bool multipage, List<wchar_t*>* filenames, int indices[], int indexCount, int id )
        : AsyncInvokeArg( model, id )
    {
        m_path = path;
        m_format = format;
        m_multipage = multipage;
        m_filenames = filenames;
        m_indices = indices;
        m_indexCount = indexCount;
    }

    virtual ~SaveAsyncArg()
    {
        if ( m_path ) delete m_path;
        if ( m_filenames )
        {
            m_filenames->destroy();

            delete m_filenames;
        }
    }

    inline wchar_t* getPath() { return m_path; }
    inline List<wchar_t*>& getFilenames() { return *m_filenames; }
    inline int* getIndices() { return m_indices; }
    inline int getIndexCount() { return m_indexCount; }
    inline DocumentFormat getFormat() { return m_format; }
    inline bool getIsMultipage() { return m_multipage; }
};


class ImageAsyncArg : public AsyncInvokeArg
{
public:

    ImageAsyncArg( PluginModel* model, Pixels& image )
        : AsyncInvokeArg( model )
    {
        m_image = image;
    }

    virtual ~ImageAsyncArg() { }

    Pixels& getImage() { return m_image; }

private:

    //bool m_add;
    Pixels m_image;
};


class ToolStateAsyncArg : public AsyncInvokeArg
{
public:

    ToolStateAsyncArg( PluginModel* model, int toolId, bool toolState )
        : AsyncInvokeArg( model )
    {
        m_toolId = toolId;
        m_toolState = toolState;
    }

    virtual ~ToolStateAsyncArg() { }

    inline int getToolId() { return m_toolId; }
    inline int getToolState() { return m_toolState; }

private:

    int m_toolId;
    bool m_toolState;
};


class PluginAsyncCallback : public AsyncInvoke
{
public:

    AsyncCallback callback;
    AsyncInvokeArg* arg;
    void* handle;

    PluginAsyncCallback() : arg( 0 ), handle( 0 ), callback( 0 ) { }

    virtual ~PluginAsyncCallback()
    {
        delete arg;
    }

    virtual AsyncCallback getCallback() { return callback; }
    virtual AsyncInvokeArg* getArg() { return arg; }
};


void* beginInvoke( AsyncInvoke* asyncInvoke );
